package server

import (
	"context"
	"log"
	"sync"
)

// ClientsManager 管理所有客户端连接和房间
type ClientsManager struct {
	allClients    map[string]*Client
	allRooms      map[string]*Room
	inRoomClients map[string]*RoomClient
	mu            sync.RWMutex
	ctx           context.Context
	cancel        context.CancelFunc
}

// NewClientsManager 创建一个新的客户端管理器
func NewClientsManager() *ClientsManager {
	ctx, cancel := context.WithCancel(context.Background())
	return &ClientsManager{
		allClients:    make(map[string]*Client),
		allRooms:      make(map[string]*Room),
		inRoomClients: make(map[string]*RoomClient),
		ctx:           ctx,
		cancel:        cancel,
	}
}

// AddClient 添加一个客户端连接
func (cm *ClientsManager) AddClient(client *Client) {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	cm.allClients[client.id] = client
}

// RemoveClient 移除一个客户端连接
func (cm *ClientsManager) RemoveClient(clientID string) {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	if client, exists := cm.allClients[clientID]; exists {
		client.Close()
		delete(cm.allClients, clientID)
	}
}

// ClientClosed 处理客户端关闭事件
func (cm *ClientsManager) ClientClosed(client *Client) {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.LeaveRoom()
		delete(cm.inRoomClients, client.id)
	} else {
		log.Printf("Client %s was not in any room", client.id)
	}

	delete(cm.allClients, client.id)
}

// CloseAllClients 关闭所有客户端连接
func (cm *ClientsManager) CloseAllClients() {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	for _, client := range cm.allClients {
		client.Close()
	}

	// 关闭所有房间
	for _, room := range cm.allRooms {
		room.Close()
	}

	cm.allClients = make(map[string]*Client)
	cm.inRoomClients = make(map[string]*RoomClient)
	cm.allRooms = make(map[string]*Room)
}

// JoinRoom 处理客户端加入房间请求
func (cm *ClientsManager) JoinRoom(joinRoomInfo JoinRoomInfo, client *Client) {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	if joinRoomInfo.Room == "" {
		log.Printf("Join room failed: room name is empty for client %s", client.id)
		return
	}
	// 添加日志，检查请求中的用户ID与实际客户端ID是否匹配
	log.Printf("JoinRoom request - Room: %s, RequestUserID: %s, ActualClientID: %s",
		joinRoomInfo.Room, joinRoomInfo.UserID, client.id)

	// 如果请求中的UserID与实际客户端ID不匹配，记录警告
	if joinRoomInfo.UserID != "" && joinRoomInfo.UserID != client.id {
		log.Printf("WARNING: JoinRoom request contains mismatched UserID. Using actual client ID: %s", client.id)
	}

	// 检查客户端是否已经在其他房间中
	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		if roomClient.room.roomName == joinRoomInfo.Room {
			log.Printf("Client %s is already in the requested room %s", client.id, joinRoomInfo.Room)
			return
		} else {
			log.Printf("Client %s will be moved from room %s to room %s",
				client.id, roomClient.room.roomName, joinRoomInfo.Room)
			// 先让客户端离开当前房间
			roomClient.LeaveRoom()
			delete(cm.inRoomClients, client.id)
		}
	}

	// 始终使用当前客户端的ID加入房间，忽略请求中的UserID
	cm.clientAddRoom(client, joinRoomInfo.Room)
}

// removeRoom 从管理器中移除房间
func (cm *ClientsManager) removeRoom(roomName string) {
	log.Printf("房间最后一个人离开准备清除房间: %s", roomName)

	go func() { //启动一个新的 goroutine ，不然会死锁
		cm.mu.Lock()
		defer cm.mu.Unlock()

		if _, exists := cm.allRooms[roomName]; exists {
			delete(cm.allRooms, roomName)
			log.Printf("Room %s removed", roomName)
		}
	}()
}

// clientAddRoom 将客户端添加到房间
func (cm *ClientsManager) clientAddRoom(client *Client, roomName string) {
	var room *Room
	var exists bool

	// 检查房间是否存在，不存在则创建
	room, exists = cm.allRooms[roomName]
	if !exists {
		room = NewRoom(roomName, cm.removeRoom)
		cm.allRooms[roomName] = room
	}

	// 创建房间客户端
	roomClient := NewRoomClient(client, room)

	// 添加到房间客户端映射
	cm.inRoomClients[client.id] = roomClient

	// 加入房间
	room.JoinRoom(roomClient)
}

// RequestRoomOwner 处理请求成为房主
func (cm *ClientsManager) RequestRoomOwner(client *Client, data string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.RoomOwnerRequest(roomClient)
	}
}

// ResponceRoomOwnerReq 处理房主转移响应
func (cm *ClientsManager) ResponceRoomOwnerReq(client *Client, result string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.ResponceOwner(result)
	}
}

// ChangeRoomPlayFile 处理更改播放文件
func (cm *ClientsManager) ChangeRoomPlayFile(client *Client, fileID string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.ChangePlayFile(fileID)
	}
}

// ChangeRoomPlayState 处理更改播放状态
func (cm *ClientsManager) ChangeRoomPlayState(client *Client, stateCmd string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.ChangePlayState(stateCmd)
	}
}

// RoomObjSynchronization 处理对象同步
func (cm *ClientsManager) RoomObjSynchronization(client *Client, info string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.RoomObjSynchronization(info)
	}
}

// GetRoomPlayProgress 获取播放进度（通知房主同步房间播放进度）
func (cm *ClientsManager) GetRoomPlayProgress(client *Client, data string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()
	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.GetRoomPlayProgress(data)
	}
}

// SyncRoomPlayProgress 处理响应房间播放进度
func (cm *ClientsManager) SyncRoomPlayProgress(client *Client, data string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.PushRoomPlayProgress(data)
	}
}

// RoomMultiObjSync 处理多对象同步
func (cm *ClientsManager) RoomMultiObjSync(client *Client, data string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.RoomMultiObjSync(data)
	}
}

// RoomRoomOwnerForcibly 强制成为房主
func (cm *ClientsManager) RoomRoomOwnerForcibly(client *Client, data string) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	if roomClient, exists := cm.inRoomClients[client.id]; exists {
		roomClient.room.BecomeOwner(roomClient, data)
	}
}

// GetClient 获取客户端
func (cm *ClientsManager) GetClient(clientID string) (*Client, bool) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	client, exists := cm.allClients[clientID]
	return client, exists
}

// GetRoom 获取房间
func (cm *ClientsManager) GetRoom(roomName string) (*Room, bool) {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	room, exists := cm.allRooms[roomName]
	return room, exists
}

// Close 关闭客户端管理器
func (cm *ClientsManager) Close() {
	cm.cancel()
	cm.CloseAllClients()
}
